/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行，false 表非立即执行
 */
export function debounce(func, wait, immediate) {
  let timeout;

  return function () {
    const context = this;
    const args = arguments;
    try {
      if (timeout) {
        clearTimeout(timeout);
      }
      if (immediate) {
        const callNow = !timeout;
        timeout = setTimeout(() => {
          timeout = null;
        }, wait);
        if (callNow) {
          func.apply(context, args);
        }
      } else {
        timeout = setTimeout(function () {
          func.apply(context, args);
        }, wait);
      }
    } catch (e) {
      console.log(e);
    }
  };
}
/**
 * @desc 函数节流
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param type 1 表时间戳版，2 表定时器版
 */
export function throttle(func, wait, type) {
  let previous = 0;
  let timeout;

  return function () {
    const context = this;
    const args = arguments;
    if (type === 1) {
      const now = Date.now();

      if (now - previous > wait) {
        func.apply(context, args);
        previous = now;
      }
    } else if (type === 2) {
      if (!timeout) {
        timeout = setTimeout(() => {
          timeout = null;
          func.apply(context, args);
        }, wait);
      }
    }
  };
}

// 代理法
export function deepClone(obj) {
  function isObject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null;
  }
  if (!isObject(obj)) {
    throw new Error('obj 不是一个对象！');
  }

  const isArray = Array.isArray(obj);
  const cloneObj = isArray
    ? [...obj]
    : {
        ...obj,
      };
  Reflect.ownKeys(cloneObj).forEach((key) => {
    cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
  });

  return cloneObj;
}

// 判断两个对象的值是否一致
export function isObjectValueEqual(a, b) {
  // 判断两个对象是否指向同一内存，指向同一内存返回true
  if (a === b) {
    return true;
  }
  // 获取两个对象键值数组
  const aProps = Object.getOwnPropertyNames(a);
  const bProps = Object.getOwnPropertyNames(b);
  // 判断两个对象键值数组长度是否一致，不一致返回false
  if (aProps.length !== bProps.length) {
    return false;
  }
  // 遍历对象的键值
  for (const prop in a) {
    // 判断a的键值，在b中是否存在，不存在，返回false
    if (b.hasOwnProperty(prop)) {
      // 判断a的键值是否为对象，是则递归，不是对象直接判断键值是否相等，不相等返回false
      if (typeof a[prop] === 'object') {
        if (!isObjectValueEqual(a[prop], b[prop])) {
          return false;
        }
      } else if (a[prop] !== b[prop]) {
        return false;
      }
    } else {
      return false;
    }
  }
  return true;
}

// 选择选项 格式 对象
export function optionsToObj(arr, key = 'value', val = 'label', obj = {}) {
  arr.forEach((item) => {
    obj[item[key]] = item[val];
  });
  return obj;
}

/**
 * 系统
 */
export const SysUtils = {
  // 获取设备类型
  getDeviceType() {
    // 101 移动H5 201 PCH5 301 Android 302 IOS 401 Windows终端 402 Mac终端
    const agent = navigator.userAgent.toLowerCase();
    // 非终端都按H5算
    if (/windows/.test(agent)) {
      return 201; // 'windows pc';
    }
    if (/iphone|ipod/.test(agent) && /mobile/.test(agent)) {
      return 101; // 'iphone';
    }
    if (/ipad/.test(agent) && /mobile/.test(agent)) {
      return 201; // 'ipad';
    }
    if (/android/.test(agent) && /mobile/.test(agent)) {
      return 101; // 'android';
    }
    if (/linux/.test(agent)) {
      return 201; // 'linux pc';
    }
    if (/mac/.test(agent)) {
      return 201; // 'mac';
    }
    return 201; // 'other';
  },

  // 获取登录接口日志记录数据
  getSupplement(account) {
    const obj = {
      deviceType: '', // 登录设备类型
      accountType: 1, // 登录用户类型
      deviceKey: '', // 登录设备mac地址
      deviceVersion: '', // 登录设备系统版本
      ip: store.getters.userIp, // 登录ip
      version: APPCONFIG.VUE_APP_BASE_VERSION, // 产品版本号
      account: '', // 登录账号
    };
    // 终端打包时携带的参数
    const urlParams = new URLSearchParams(new URL(window.location).search);

    const devicetype = Number(urlParams.get('deviceType'));
    obj.deviceType = devicetype || this.getDeviceType();

    const deviceKey = urlParams.get('deviceKey');
    obj.deviceKey = deviceKey || '';

    const deviceVersion = urlParams.get('deviceVersion');
    obj.deviceVersion = deviceVersion || '';

    obj.account = account || '';
    return obj;
  },

  getURLSupplement(account) {
    const str = JSON.stringify(this.getSupplement(account));
    return encodeURIComponent(str);
  },
};
